package cn.tramy.pinxian.wind.command.dispatch

import cn.tramy.pinxian.common.exception.CommonException
import cn.tramy.pinxian.common.util.ExecuteTool
import cn.tramy.pinxian.common.util.validationRules
import cn.tramy.pinxian.wind.command.annotation.CommandHandler
import cn.tramy.pinxian.wind.command.exception.MoreThanOneHandlerException
import cn.tramy.pinxian.wind.handler.HandleContext
import cn.tramy.pinxian.wind.handler.HandlerInfo
import cn.tramy.pinxian.wind.handler.dispatch.AbstractCommonDispatcher
import cn.tramy.pinxian.wind.handler.dispatch.interceptor.DispatchInterceptor
import cn.tramy.pinxian.wind.handler.registry.HandlerRegistry
import cn.tramy.pinxian.wind.util.WindApplicationUtil
import org.springframework.transaction.annotation.Transactional


open class CommandDispatcher(handlerRegistry: HandlerRegistry) : AbstractCommonDispatcher(handlerRegistry) {

    @Transactional
    override fun dispatch(message: Any) {
        super.dispatch(message)
    }


    init {
        this.addInterceptor(CommandDispatchInterceptor())
    }

    override fun validate(handlers: List<HandlerInfo<out Any>>, message: Any): Boolean {

        validationRules {
            rule {
                ifTrue { handlers.isEmpty() }
                exception { CommonException("No Handler for command:$message") }
            }
            rule {
                ifTrue { handlers.size > 1 }
                exception { MoreThanOneHandlerException() }
            }
        }.validate()
//        ExecuteTool.conditionalException({ handlers.isEmpty() }, { CommonException("No Handler for command:$message") })
//
//        ExecuteTool.conditionalException({ handlers.size > 1 }, { MoreThanOneHandlerException() })

        return super.validate(handlers, message)
    }

    override fun groupName(): String {
        return CommandHandler::class.java.name
    }

    private class CommandDispatchInterceptor() : DispatchInterceptor {
        override fun beforeDispatch(message: Any): Any {
            WindApplicationUtil.registerSynchronization()
            HandleContext.current().putValue("COMMAND", message)
            return message
        }

        override fun afterDispatch(message: Any) {
        }
    }
}